import java.util.ArrayList;

import particle.Repeller;
import processing.core.PApplet;
import processing.core.PVector;
import autonomous.FlockBoid;
import autonomous.FlockPopulation;

public class Flocking extends PApplet {
	// Click mouse to add boids into the system

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static void main(String args[]) {
		PApplet.main(new String[] { "--present", "Flocking" });
	}

	FlockPopulation fPop;
	// Flock flock;
	ArrayList<Repeller> repellers;

	public void setup() {

		size(800, 600);

		repellers = new ArrayList<Repeller>();
		for (int i = 0; i < 7; i++) {
			repellers.add(new Repeller(this, random(width), random(height)));
		}
		float maxspeed = 3;
		float maxforce = (float) 0.1;
		int mutationRate = 2;

		fPop = new FlockPopulation(this, 10, mutationRate, 30, maxspeed,
				maxforce);

		smooth();
	}

	public void draw() {
		// set background color
		background(80, 25, 155);

		// draw repellers
		for (int i = 0; i < repellers.size(); i++) {
			Repeller r = repellers.get(i);
			r.display();
			r.drag();
		}

		// bring population to live
		fPop.live();

		// apply force to fishes
		applyRepellers();

		// remove catched fishes
		checkRepellers();

		fPop.naturalSelection();

		if(fPop.flock.size() < 80)
		fPop.generate();

		displayInfo();
	}

	void displayInfo() {
		// String answer = fPop.getBest();
		textAlign(LEFT);
		fill(200);
		// text(answer, 20, 100);
		text("# of members alive: " + fPop.flock.size(), 20, 20);

		text("total generations: " + fPop.getGenerations(), 20, 40);
		// text("average fitness: " + fPop.getAverageFitness(), 20, 155);
		// text("total population: " + popmax, 20, 170);
		// text("mutation rate: " + (int) (mutationRate * 100) + "%", 20, 185);
	}

	public void applyRepellers() {
		for (int i = fPop.flock.size() - 1; i > 0; i--) {
			FlockBoid f = fPop.flock.getBoid(i);
			for (int j = repellers.size() - 1; j > 0; j--) {
				Repeller r = repellers.get(j);
				PVector repel = r.pushBoid(f);
				f.applyForce(repel);
			}
		}
	}

	public void checkRepellers() {
		for (int i = fPop.flock.size() - 1; i > 0; i--) {
			FlockBoid f = fPop.flock.getBoid(i);
			for (int j = repellers.size() - 1; j > 0; j--) {
				Repeller r = repellers.get(j);
				boolean motionless = r.motion(f, r);
				if (motionless)
					fPop.flock.removeBoid(i);
			}
		}
		if (fPop.flock.size() == 1)
			fPop.flock.removeBoid(0);
	}

	public void mousePressed() {
		for (int i = 0; i < repellers.size(); i++) {
			Repeller r = repellers.get(i);
			r.clicked(mouseX, mouseY);
		}
	}

	public void mouseReleased() {
		for (int i = 0; i < repellers.size(); i++) {
			Repeller r = repellers.get(i);
			r.stopDragging();
		}
	}

}
